﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace ComicsEditor
{
    public class BalloonRectInstrument : Instrument, IShape
    {
        public DashedRect DashedRect = null;
        public Balloon Balloon = null;

        private bool include = true;

        public BalloonRectInstrument()
        {
        }

        public override void Bind(PageInfo PageInfo)
        {
            base.Bind(PageInfo);

            if (DashedRect != null)
                DashedRect.Dispose();
            DashedRect = new DashedRect(Page, Rectangle.Empty);
            DashedRect.Hide();
        }

        public void Enable(bool include)
        {
            Enable();
            this.include = include; 
        }

        public override bool Activate(Point point, out Point offset)
        {
            offset = Point.Empty;
            DashedRect.Rectangle = new Rectangle(point, new Size(1, 1));
            DashedRect.Show();
            return true;
        }

        public override void Drag(Point newPoint, Point offset, Point deltaActivate, Point deltaMove)
        {
            if (deltaActivate.X >= 0)
            {
                DashedRect.Rectangle.X = newPoint.X - deltaActivate.X;
                DashedRect.Rectangle.Width = deltaActivate.X + 1;
            }
            else
            {
                DashedRect.Rectangle.X = newPoint.X;
                DashedRect.Rectangle.Width = 1 - deltaActivate.X;
            }
            if (deltaActivate.Y >= 0)
            {
                DashedRect.Rectangle.Y = newPoint.Y - deltaActivate.Y;
                DashedRect.Rectangle.Height = deltaActivate.Y + 1;
            }
            else
            {
                DashedRect.Rectangle.Y = newPoint.Y;
                DashedRect.Rectangle.Height = 1 - deltaActivate.Y;
            }
            if (DashedRect.Rectangle.X < 0)
            {
                DashedRect.Rectangle.Width += DashedRect.Rectangle.X;
                DashedRect.Rectangle.X = 0;
            }
            if (DashedRect.Rectangle.Y < 0)
            {
                DashedRect.Rectangle.Height += DashedRect.Rectangle.Y;
                DashedRect.Rectangle.Y = 0;
            }
            if (DashedRect.Rectangle.Right > Page.Width)
                DashedRect.Rectangle.Width = Page.Width - DashedRect.Rectangle.X;
            if (DashedRect.Rectangle.Bottom > Page.Height)
                DashedRect.Rectangle.Height = Page.Height - DashedRect.Rectangle.Y;
            Page.Changed = true;
        }

        public override void Deactivate()
        {
            DashedRect.Hide();
            if (DashedRect.Rectangle.Width > 1 && DashedRect.Rectangle.Height > 1)
            {
                if (include)
                {
                    if (Balloon != null && Balloon.Include(this))
                    {
                    }
                    else
                    {
                        Balloon balloon = new Balloon(Page, new Contour(this));
                        pageInfo.Balloons.Add(balloon);
                        if (pageInfo.BalloonCreate != null)
                            pageInfo.BalloonCreate(balloon);
                    }
                }
                else
                    if (Balloon != null)
                        Balloon.Exclude(this);
            }
        }

        Point IShape.TopLeft
        {
            get 
            {
                return DashedRect.Rectangle.Location;
            }
        }

        bool IShape.Contains(Point p)
        {
            return DashedRect.Rectangle.Contains(p);
        }

        internal static Point[] Dirs = BalloonFillInstrument.Dirs;
        int IShape.GetOutsideDir(Point p, int curDir)
        {
            int i;
            Rectangle rect = DashedRect.Rectangle;
            if (p.X < rect.X - 1 || p.X > rect.Right)
                return -1;
            if (p.Y < rect.Y - 1 || p.Y > rect.Bottom)
                return -1;
            for (i = 0; i < 8 && rect.Contains(p.X + Dirs[(i + curDir)%8].X, p.Y + Dirs[(i + curDir)%8].Y); i++);
            for (; i < 8 && !rect.Contains(p.X + Dirs[(i + curDir)%8].X, p.Y + Dirs[(i + curDir)%8].Y); i++);
            return (i + curDir)%8;
        }

        int IShape.GetOutsideCWDir(Point p, int curDir)
        {
            int i;
            Rectangle rect = DashedRect.Rectangle;
            if (p.X < rect.X - 1 || p.X > rect.Right)
                return -1;
            if (p.Y < rect.Y - 1 || p.Y > rect.Bottom)
                return -1;
            for (i = 8; i > 0 && rect.Contains(p.X + Dirs[(i + curDir)%8].X, p.Y + Dirs[(i + curDir)%8].Y); i--);
            for (; i > 0 && !rect.Contains(p.X + Dirs[(i + curDir)%8].X, p.Y + Dirs[(i + curDir)%8].Y); i--);
            return (i + curDir)%8;
        }

        int IShape.GetInsideDir(Point p, int curDir)
        {
            throw new NotImplementedException();
        }

        int IShape.GetInsideCWDir(Point p, int curDir)
        {
            throw new NotImplementedException();
        }

        object IShape.GetPosition(Point p)
        {
            return p;
        }

        Point IShape.NextPoint(ref object position)
        {
            Rectangle rect = DashedRect.Rectangle;
            Point p = (Point)position;
            if (p.Y == rect.Y && p.X > rect.X)
                p.X--;
            else if (p.X == rect.X && p.Y < rect.Bottom - 1)
                p.Y++;
            else if (p.Y == rect.Bottom - 1 && p.X < rect.Right - 1)
                p.X++;
            else if (p.X == rect.Right - 1 && p.Y > rect.Y)
                p.Y--;
            position = p;
            return p;
        }

        Point IShape.PrevPoint(ref object position)
        {
            Rectangle rect = DashedRect.Rectangle;
            Point p = (Point)position;
            if (p.Y == rect.Y && p.X < rect.Right - 1)
                p.X++;
            else if (p.X == rect.X && p.Y > rect.Y)
                p.Y--;
            else if (p.Y == rect.Bottom - 1 && p.X > rect.X)
                p.X--;
            else if (p.X == rect.Right - 1 && p.Y < rect.Bottom - 1)
                p.Y++;
            position = p;
            return p;
        }
    }
}
